<template>
  <el-container class="page-table-ctn" v-loading="tableLoading">
    <el-table v-bind="$attrs" v-on="$listeners" :data="filterData" ref="pageTable">
      <slot></slot>
      <el-table-column width="40" fixed="right" v-if="dynamicColumnSetting">
        <template slot="header">
          <el-button
            size="small"
            type="text"
            icon="el-icon-setting"
            style="padding:0;"
            @click="dynColSettingDialogVisible = true"
          ></el-button>
        </template>
      </el-table-column>
    </el-table>
    <el-footer class="footer" v-if="paging">
      <div class="size-info">
        <span v-if="totalSize > 1">显示第 {{start}} 条到第 {{end}} 条的数据，</span>
        共{{ totalSize }} 条数据
      </div>
      <el-pagination
        v-bind="$attrs"
        v-on="$listeners"
        :pager-count="5"
        :layout="layout"
        :page-sizes="pageSizes"
        :page-size="currPageSize"
        :current-page="currPage"
        :total="totalSize"
        style="float:right"
        @current-change="handleCurrentChange"
        @size-change="handleSizeChange"
      ></el-pagination>
    </el-footer>

    <el-dialog
      title="展示列设置"
      class="dyn-col-ctn"
      :visible.sync="dynColSettingDialogVisible"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :show-close="false"
    >
      <el-checkbox-group v-model="visibleIndexs" :min="1">
        <el-checkbox
          v-for="colInfo in columnInfos"
          :label="colInfo.index"
          :key="colInfo.index"
          :disabled="colInfo.disabled"
        >{{ colInfo.label }}</el-checkbox>
      </el-checkbox-group>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dynColSettingCancel">关 闭</el-button>
        <el-button type="primary" @click="dynColSettingConfirm">确 定</el-button>
      </span>
    </el-dialog>
  </el-container>
</template>

<script>
export default {
  name: "page-table",
  props: {
    data: {
      type: Array,
      require: true,
      default: _ => []
    },
    currentPage: {
      type: Number,
      default: 1
    },
    pageSize: {
      type: Number,
      default: 10
    },
    pageSizes: {
      type: Array,
      default: _ => [10, 30, 50, 100]
    },
    layout: {
      type: String,
      default: "sizes, prev, pager, next, jumper"
    },
    paging: {
      // 是否分页，默认为true，即分页。（不分页时将每页条数设置最大。）
      type: Boolean,
      default: true
    },

    dynamicColumnSetting: {
      // 是否开启动态列设置
      type: Boolean,
      default: false
    },
    alwaysShowColumnIndexs: {
      // 总是展示的列下标（不允许隐藏）。列下标值是从 0 开始
      type: Array,
      default: _ => []
    },
    hidenColumnIndexs: {
      // 初始隐藏的列下标。列下标值是从 0 开始
      type: Array,
      default: _ => []
    },

    backendPaging: {
      // 是否开启后端分页，默认为false，即前端分页。
      type: Boolean,
      default: false
    },
    backendPagingFuncName: {
      // 后端分页触发的方法名
      type: String,
      default: "backendPagingFunc"
    }
  },
  data() {
    return {
      allData: this.data, // 全量表格数据(前端分页)
      filterData: [], // 表格展示数据
      start: 1,
      end: 1,
      totalSize: this.data.length,
      currPageSize: this.paging ? this.pageSize : Number.MAX_SAFE_INTEGER,
      currPage: this.currentPage,

      dynColSettingDialogVisible: false, // '展示列设置'弹窗开关
      columnInfos: [], // 所有列信息
      visibleIndexs: [], // 可见列的下标集合
      hidenIndexs: this.hidenColumnIndexs, // 不可见列(隐藏列)的下标集合

      tableLoading: false // 后端分页的loading
    };
  },
  methods: {
    handleSizeChange(value) {
      this.currPage = 1;
      this.currPageSize = value;
      this.handleChange();
    },
    handleCurrentChange(value) {
      this.currPage = value;
      this.handleChange();
    },
    handleChange(reset) {
      // reset：是否重置页码
      if (reset) {
        this.currPage = 1;
      }
      if (this.backendPaging) {
        this.backendPagingFunc();
      } else {
        this.renderTable();
        if (this.dynamicColumnSetting) {
          this.dynColSettingConfirm();
        }
      }
      
    },
    renderTable() {
      if (this.totalSize > this.currPageSize) {
        // 总行数大于一页
        let startIndex = (this.currPage - 1) * this.currPageSize,
          endIndex = this.currPage * this.currPageSize;
        this.filterData = this.allData.slice(startIndex, endIndex); //[start,end)
        this.start = startIndex + 1;
        this.end = this.start + this.filterData.length - 1;
      } else if (this.totalSize > 0) {
        // 总行数小于等于一页
        this.currPage = 1;
        this.start = 1;
        this.end = this.totalSize;
        this.filterData = this.allData;
      } else {
        // 无数据
        this.currPage = 1;
        this.start = 0;
        this.end = 0;
        this.filterData = [];
      }
    },
    setData(value) {
      if (this.backendPaging) {
        this.callback(value);
      } else {
        this.allData = value;
        this.totalSize = value.length;
        this.renderTable();
      }
    },

    dynColSettingCancel() {
      let self = this;
      this.dynColSettingDialogVisible = false;
      // 重置可见列下标集合
      var tempVisibleIndexs = [];
      this.columnInfos.forEach(columnInfo => {
        if (self.hidenIndexs.indexOf(columnInfo.index) === -1) {
          tempVisibleIndexs.push(columnInfo.index);
        }
      });
      this.visibleIndexs = tempVisibleIndexs;
    },
    dynColSettingConfirm() {
      let self = this;
      var tmpHideIndexs = [],
        tmpShowIndexs = [];

      self.columnInfos.forEach(columnInfo => {
        if (self.visibleIndexs.indexOf(columnInfo.index) === -1) {
          tmpHideIndexs.push(columnInfo.index);
        }
      });

      tmpShowIndexs = self.hidenIndexs.filter(
        index => tmpHideIndexs.indexOf(index) === -1
      );

      this.showColumns(tmpShowIndexs);
      self.hidenIndexs = tmpHideIndexs;
      this.hideColumns(self.hidenIndexs);

      this.dynColSettingDialogVisible = false;
    },
    showColumns(indexs) {
      this.oprColumns(indexs, "");
    },
    hideColumns(indexs) {
      this.oprColumns(indexs, "none");
    },
    oprColumns(indexs, display) {
      if (!indexs || indexs.length === 0) {
        return;
      }
      let self = this;
      let classSelector = indexs
        .map(
          index =>
            `.${self.$refs.pageTable.$slots.default[index].componentInstance.columnId}:not(.is-hidden)`
        )
        .join(",");
      // 关键代码！！！
      self.$nextTick(_ => {
        self.$el.querySelectorAll(classSelector).forEach(item => {
          item.style.display = display;
        });
      });
    },
    backendPagingFunc() {
      this.tableLoading = true;

      this.$emit(
        this.backendPagingFuncName,
        this.currPage,
        this.currPageSize,
        // 第四个参数是一个方法，用于处理后台分页请求返回的数据。等同于直接调用 callback方法
        res => {
          this.callback(res);
        }
      );
    },
    // 后台分页请求返回时的回调方法，设置分页信息，渲染表格
    callback(res) {
      // res 的预期格式是 {data:[], total:10}
      this.filterData = res.data;
      this.totalSize = res.total;

      let startIndex = (this.currPage - 1) * this.currPageSize;
      this.start = startIndex + 1;
      this.end = this.start + this.filterData.length - 1;

      if (this.dynamicColumnSetting) {
        this.dynColSettingConfirm();
      }

      this.tableLoading = false;
    },

    //<el-table>自带的方法 start
    setCurrentRow(row) {
      this.$refs.pageTable.setCurrentRow(row);
    }
    //...
    //<el-table>自带的方法 end
  },
  watch: {
    data() {
      if (!this.backendPaging) {
        this.setData(this.data ? this.data : []);
      }
    }
  },
  mounted() {
    let self = this;

    if (self.$refs.pageTable.$slots.default && self.dynamicColumnSetting) {
      self.$refs.pageTable.$slots.default.forEach((columnIns, index) => {
        let props = columnIns.componentOptions.propsData;
        if (props.fixed === "right" && !props.label) {
          // 设置列，不记录
          return;
        }
        // 保存所有列信息
        self.columnInfos.push({
          label: props.type === "selection" ? "复选框" : props.label,
          index: index,
          disabled: props.type === "selection" ? true : false // 默认checkbox不可隐藏
        });
        // 记录初始展示的列
        if (self.hidenIndexs.indexOf(index) === -1) {
          self.visibleIndexs.push(index);
        }
      });
      // 总是显示的列，不可隐藏
      self.alwaysShowColumnIndexs.forEach(
        index => (self.columnInfos[index].disabled = true)
      );
      if (!this.backendPaging) {
        // 处理初始隐藏列
        self.hideColumns(self.hidenIndexs);
      }
    }

    if (this.backendPaging) {
      // 触发后端分页查询
      this.backendPagingFunc();
    }
  }
};
</script>

<style lang="scss" scoped>
.page-table-ctn {
  > .el-table {
    width: auto;
    margin: 14px;
    border: 1px solid #ebeef5;
    border-bottom: unset;
  }
  > .footer {
    height: 40px !important;
    .size-info {
      display: inline;
      font-size: 12px;
      color: #666666;
    }
  }
  > .dyn-col-ctn {
    .el-checkbox {
      margin-bottom: 10px;
    }
  }
}
</style>
